package com;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class EchoServer {

    private final static int DEFAULT_PORT = 1117;

    private int port;

    public EchoServer(int port) {
        this.port = port;
    }

    public void start(){

        try (ServerSocketChannel channel = ServerSocketChannel.open()){

            ServerSocket serverSocket = channel.socket();

            SocketAddress addr = new InetSocketAddress(port);

            serverSocket.bind(addr);

            channel.configureBlocking(false);

            Selector selector = Selector.open();

            channel.register(selector, SelectionKey.OP_ACCEPT);


            while (true){

                selector.select();

                Set<SelectionKey> readyKeys = selector.selectedKeys();

                Iterator<SelectionKey> iter = readyKeys.iterator();

                while (iter.hasNext()){

                    SelectionKey key = iter.next();

                    iter.remove();

                    if(key.isAcceptable()){

                        ServerSocketChannel serverSocketChannel = (ServerSocketChannel) key.channel();

                        SocketChannel client = serverSocketChannel.accept();

                        System.out.println(client + " has connect");

                        client.configureBlocking(false);

                        SelectionKey key1 = client.register(selector,SelectionKey.OP_READ | SelectionKey.OP_WRITE);

                        ByteBuffer buffer = ByteBuffer.allocate(100);

                        key1.attach(buffer);

                    }

                    if(key.isReadable()){

                        SocketChannel client = (SocketChannel) key.channel();

                        ByteBuffer buffer = (ByteBuffer) key.attachment();

                        client.read(buffer);

                    }

                    if(key.isWritable()){

                        SocketChannel client = (SocketChannel) key.channel();

                        ByteBuffer buffer = (ByteBuffer) key.attachment();

                        buffer.flip();

                        client.write(buffer);

                        buffer.compact();

                    }

                }

            }


        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {

        int port;

        if(args.length == 0)
            port = DEFAULT_PORT;

        try {
            port = Integer.parseInt(args[0]);
        }catch (RuntimeException e){
            port = DEFAULT_PORT;
        }


        EchoServer server = new EchoServer(port);

        server.start();

    }

}
